package com.example.ktdemo.savemedia;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;

import androidx.core.app.ActivityCompat;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.file.Files;

/**
 * FileName: MediaPicUtils
 * Author: lzt
 * Date: 2022/6/21 13:57
 * 使用该类之前，必须提前申请读写权限
 * code review by lzt 20230302--适配视频插入图库，图片插入图库
 */
public class MediaPicUtils implements Serializable {

    //请求code
    public static final int CODE_REQ = 10086;
    //默认保存目录
    private static final String DefaultPath = Environment.DIRECTORY_PICTURES;
    //默认的扩展目录
    private static final String DEFAULT_EXT_PATH = "JeaginePic";

    //内部实现方法，只能内部调用---------------------------------------------------------------------

    /**
     * 安卓Q以后文件复制
     */
    private static void copyFileAfterQ(Context context, ContentResolver localContentResolver,
                                       File tempFile, Uri localUri) throws IOException {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q) {
            //拷贝文件到相册的uri,android10及以上得这么干，否则不会显示。可以参考ScreenMediaRecorder的save方法
            OutputStream os = localContentResolver.openOutputStream(localUri);
            Files.copy(tempFile.toPath(), os);
            os.close();
            tempFile.delete();
        }
    }

    /**
     * 创建目录or文件
     */
    private static void createFile(File file, boolean isFile) {// 创建文件
        try {
            if (file != null && !file.exists()) {// 如果文件不存在
                if (file.getParentFile() != null && !file.getParentFile().exists()) {// 如果文件父目录不存在
                    createFile(file.getParentFile(), false);
                } else {// 存在文件父目录
                    if (isFile) {// 创建文件
                        try {
                            boolean createResult = file.createNewFile();// 创建新文件
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } else {
                        boolean mkResult = file.mkdir();// 创建目录
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取图片的ContentValue--Q以后
     */
    public static ContentValues getContentValuesAfterQ(String rootPath, File paramFile, String mimeType,
                                                       String desc) {
        long timestamp = System.currentTimeMillis();
        ContentValues localContentValues = new ContentValues();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            localContentValues.put(MediaStore.Images.Media.RELATIVE_PATH, rootPath);
        }
        localContentValues.put(MediaStore.Images.Media.TITLE, paramFile.getName());
        localContentValues.put(MediaStore.Images.Media.DISPLAY_NAME, paramFile.getName());
        localContentValues.put(MediaStore.Images.Media.MIME_TYPE, mimeType);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            localContentValues.put(MediaStore.Images.Media.DATE_TAKEN, timestamp);
            localContentValues.put(MediaStore.Images.Media.ORIENTATION, 0);
        }
        localContentValues.put(MediaStore.Images.Media.DATE_MODIFIED, timestamp);
        if (!TextUtils.isEmpty(desc)) {
            localContentValues.put(MediaStore.Images.Media.DESCRIPTION, desc);
        }
        localContentValues.put(MediaStore.Images.Media.DATE_ADDED, timestamp);
        localContentValues.put(MediaStore.Images.Media.DATA, paramFile.getAbsolutePath());
        localContentValues.put(MediaStore.Images.Media.SIZE, paramFile.length());
        return localContentValues;
    }


    /**
     * 保存到系统--Q以后
     *
     * @param externalUrl MediaStore.Images.Media.EXTERNAL_CONTENT_URI
     *                    MediaStore.Video.Media.EXTERNAL_CONTENT_URI
     */
    private static String saveToSystemAfterQ(Context context, ContentValues contentValues,
                                             String fileFullPath, Uri externalUrl) throws Exception {
        ContentResolver contentResolver = context.getContentResolver();
        File tempFile = new File(fileFullPath);
        Uri external = externalUrl;
        Uri uri = contentResolver.insert(external, contentValues);
        copyFileAfterQ(context, contentResolver, tempFile, uri);
        contentValues.clear();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
        }
        context.getContentResolver().update(uri, contentValues, null, null);
        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
        return MediaUriUtils.getFilePathFromContentUri(context, uri);
    }

    /**
     * 保存图片到指定目录
     *
     * @param parentPath /dd/ddd/ddx/
     * @param fileName   dsafdasf.jpg
     */
    private static String saveImageTargetPath(Context context, Bitmap source, String parentPath, String fileName) {
        File fileDir = new File(parentPath);
        if (!fileDir.exists()) {
            createFile(fileDir, false);
        }
        File f = new File(parentPath + fileName);
        if (!fileDir.exists()) {
            createFile(f, true);
        }
        try {
            FileOutputStream out = new FileOutputStream(f);
            source.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
            return parentPath + fileName;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


    /**
     * 保存图片到系统
     *
     * @return 保存图片路径
     */
    private static String saveMediaToSys(Context context, Bitmap bitmap, String dirType, String relativeDir,
                                         String filename, String mimeType, String description) throws Exception {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
            //首先保存
            File saveDir = Environment.getExternalStoragePublicDirectory(dirType);
            String savePath = saveDir + File.separator + relativeDir + File.separator;
            String saveResult = saveImageTargetPath(context, bitmap, savePath, filename);
            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(saveResult))));
            return saveResult;
        } else {
            String localCachePath = saveImageToApp(context, bitmap, DEFAULT_EXT_PATH, System.currentTimeMillis() + ".jpg");
            ContentValues contentValues = getContentValuesAfterQ(DefaultPath, new File(localCachePath), mimeType, description);
            return saveToSystemAfterQ(context, contentValues, localCachePath, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        }
    }


    /**
     * 保存图片到系统--传入对象是文件路径
     */
    private static String saveMediaToSysWithOutCreate(String type, Context context, String filePath,
                                                      String mimeType, String description) throws Exception {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
            //通知图库更新
            Bitmap bitmap = BitmapFactory.decodeFile(filePath);
            File picDir = Environment.getExternalStoragePublicDirectory(type);
            String savePath = picDir + File.separator;
            String saveResult = saveImageTargetPath(context, bitmap, savePath, new File(filePath).getName());
            MediaScannerConnection.scanFile(context, new String[]{saveResult},
                    new String[]{"image/*"}, (path, uri) -> {
                        Log.d("saveMedia", "saveImgToAlbum: " + path + " " + uri);
                        // Scan Completed
                    });
            return saveResult;
        } else {
            ContentValues contentValues = getContentValuesAfterQ(DefaultPath, new File(filePath), mimeType, description);
            return saveToSystemAfterQ(context, contentValues, filePath, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        }
    }


    /**
     * 保存图片到应用目录
     */
    private static String saveImageToApp(Context context, Bitmap source, String relPath, String fileName) {
        String rootPath = context.getExternalCacheDir().getAbsolutePath();
        String savePath = rootPath + File.separator + relPath + File.separator;
        return saveImageTargetPath(context, source, savePath, fileName);
    }


    /**
     * 保存视频--Q之后
     */
    private static boolean saveVideoToAlbumAfterQ(Context context, String videoFile, String mineType) {
        try {
            File tempFile = new File(videoFile);
            ContentValues contentValues = getContentValuesAfterQ(DefaultPath, tempFile, mineType, null);
            saveToSystemAfterQ(context, contentValues, videoFile, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 保存视频--Q之前
     */
    private static boolean saveVideoToAlbumBeforeQ(Context context, String videoFile, String mineType) {
        File picDir = Environment.getExternalStoragePublicDirectory(DefaultPath);
        File tempFile = new File(videoFile);
        File destFile = new File(picDir, tempFile.getName());
        FileInputStream ins = null;
        BufferedOutputStream ous = null;
        try {
            ins = new FileInputStream(tempFile);
            ous = new BufferedOutputStream(new FileOutputStream(destFile));
            long nread = 0L;
            byte[] buf = new byte[1024];
            int n;
            while ((n = ins.read(buf)) > 0) {
                ous.write(buf, 0, n);
                nread += n;
            }
            MediaScannerConnection.scanFile(
                    context,
                    new String[]{destFile.getAbsolutePath()},
                    new String[]{"video/*"},
                    (path, uri) -> {
                        Log.d("saveVideo", "saveVideoToAlbum: " + path + " " + uri);
                        // Scan Completed
                    });
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (ins != null) {
                    ins.close();
                }
                if (ous != null) {
                    ous.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    //外部实现方法，只能外部调用---------------------------------------------------------------------

    //图片相关--------------------------------------------------------------------------------------

    //保存图片到系统-------------------------------------------------------------------------------

    /**
     * 保存图片到相册--bitmap
     * 安卓29以前需要申请权限，但是这里直接强制申请
     * 保存到系统相册--picture
     */
    public static String saveImagesToSys(Activity activity, Bitmap bitmap) {
        String defaultName = System.currentTimeMillis() + ".jpg";
        String defaultDsc = "";
        return saveImagesToSys(activity, DEFAULT_EXT_PATH, defaultName, bitmap, defaultDsc);
    }

    /**
     * 保存图片到相册--bitmap
     * 安卓29以前需要申请权限，但是这里直接强制申请
     * 保存到系统相册--picture
     *
     * @param relPath      Picture目录的自定义目录名字--例如  defaultpic
     * @param targetName   保存的文件名字--例如 abc.jpg
     * @param sourceBitmap 保存的bitmap源
     * @param desc         描述
     */
    public static String saveImagesToSys(Activity activity, String relPath, String targetName,
                                         Bitmap sourceBitmap, String desc) {
        if (TextUtils.isEmpty(relPath) || TextUtils.isEmpty(targetName)) {
            return null;
        }
        String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
        if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        try {
            String mineType = "image/JPEG";
            if (targetName.toLowerCase().contains(".png")) {
                mineType = "image/PNG";
            }
            String savePath = saveMediaToSys(activity, sourceBitmap, DefaultPath,
                    relPath, targetName, mineType, desc);
            return savePath;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 保存图片到相册--file path
     */
    public static String saveImagesToSys(Activity activity, String filePath) {
        return saveImagesToSys(activity, filePath, false);
    }

    public static String saveImagesToSys(Activity activity, String filePath, boolean autoCreate) {
        String defaultName = System.currentTimeMillis() + ".jpg";
        String defaultDsc = "";
        return saveImagesToSys(activity, DEFAULT_EXT_PATH, defaultName, filePath, defaultDsc, autoCreate);
    }

    public static String saveImagesToSys(Activity activity, String relPath, String targetName,
                                         String filePath, String desc, boolean autoCreate) {
        if (TextUtils.isEmpty(relPath) || TextUtils.isEmpty(targetName)) {
            return null;
        }
        String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
        if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        try {
            String mineType = "image/JPEG";
            if (targetName.toLowerCase().contains(".png")) {
                mineType = "image/PNG";
            }
            if (autoCreate) {
                //创建bitmap，复用旧逻辑
                Bitmap sourceBitmap = BitmapFactory.decodeFile(filePath);
                return saveMediaToSys(activity, sourceBitmap, DefaultPath,
                        relPath, targetName, mineType, desc);
            } else {
                return saveMediaToSysWithOutCreate(DefaultPath, activity, filePath, mineType, desc);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //保存图片到应用内-------------------------------------------------------------------------------

    /**
     * 保存图片到应用内部目录--bitmap
     */
    public static String savePicToApp(Activity activity, Bitmap sourceBitmap) {
        String defaultName = System.currentTimeMillis() + ".jpg";
        return savePicToApp(activity, DEFAULT_EXT_PATH, defaultName, sourceBitmap);
    }


    /**
     * 保存图片到应用内部目录--bitmap
     *
     * @param relPath      目录的自定义目录名字--例如  defaultpic or default/aba/dafdsf
     * @param targetName   保存的文件名字--例如 abc.jpg
     * @param sourceBitmap 保存的bitmap源
     */
    public static String savePicToApp(Activity activity, String relPath, String targetName,
                                      Bitmap sourceBitmap) {
        return saveImageToApp(activity, sourceBitmap, relPath, targetName);
    }

    //视频相关--------------------------------------------------------------------------------------

    /**
     * 将视频保存到系统相册
     */
    public static boolean saveVideoToAlbum(Context context, String videoFile) {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
            return saveVideoToAlbumBeforeQ(context, videoFile, "video/mp4");
        } else {
            return saveVideoToAlbumAfterQ(context, videoFile, "video/mp4");
        }
    }
}
